﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace BackLib.Networking
{
    public enum PacketType
    {
        Feedback,
        ScreenShot,
        ScreenRequest,
        RequestAllowed,
        GlitchedPacket,
        MouseSend
    }

    public class TCPHandling
    {
        public TcpClient client;
        public NetworkStream clientStream;
        private DateTime Sent;
        private int Size;

        public delegate void ReceivedPacketHandler(PacketType packetType, int size, int time, int rate);
        public event ReceivedPacketHandler ReceivedPacket;

        public delegate void SentPacketHandler(PacketType packetType, int size, int time, int rate);
        public event SentPacketHandler SentPacket;

        public delegate void DisconnectedHandler();
        public event DisconnectedHandler Disconnected;

        public delegate void ReceivedScreenshotHandler(byte[] buffer);
        public event ReceivedScreenshotHandler ReceivedScreenshot;

        public delegate void ScreenshotRequestedHandler(int quality);
        public event ScreenshotRequestedHandler ScreenshotRequested;

        public delegate void RequestAllowedHandler(bool allowed);
        public event RequestAllowedHandler RequestAllowed;

        public void ReadBytes()
        {
            clientStream = client.GetStream();
            while (true)
            {
                // Get the Header Packet
                DateTime start = DateTime.Now;
                byte[] buffer = ReadData();
                PacketType packetType;
                if (buffer.Length == 1 || buffer.Length == 2)
                {
                    packetType = (PacketType)buffer[0];
                    switch (packetType)
                    {
                        case PacketType.Feedback:
                            {
                                TimeSpan timeSpan = DateTime.Now - Sent;
                                int ms = timeSpan.Milliseconds;
                                int rate = (int)Math.Round(((1000d / (double)ms) * buffer.Length) / 1024);
                                SentPacket(PacketType.ScreenShot, Size, ms, rate);
                                break;
                            }
                        case PacketType.ScreenRequest:
                            ScreenshotRequested(buffer[1]);
                            break;
                        case PacketType.RequestAllowed:
                            RequestAllowed(buffer[1] == 1 ? true : false);
                            break;
                    }
                }
                else if (buffer.Length > 2)
                {
                    // We Received a Packet
                    TimeSpan timeSpan = DateTime.Now - start;
                    int ms = timeSpan.Milliseconds;
                    int rate = (int)Math.Round(((1000d / (double)ms) * buffer.Length) / 1024);
                    ReceivedPacket(PacketType.ScreenShot, buffer.Length, ms, rate);
                    ReceivedScreenshot((byte[])buffer.Clone());
                    SendData(new byte[] { (byte)PacketType.Feedback });
                }
                else
                {
                    Disconnected();
                    break;
                }
            }
            client.Close();
        }

        private byte[] ReadData()
        {
            BinaryReader br = new BinaryReader(clientStream);
            return br.ReadBytes((int)br.BaseStream.Length);
        }

        public void SendData(byte[] buffer)
        {
            Sent = DateTime.Now;
            Size = buffer.Length;
            clientStream.Write(buffer, 0, buffer.Length);
            clientStream.Flush();
        }
    }
}
